import os
import shutil
from typing import BinaryIO, Optional, Union
from pathlib import Path
from fastapi import UploadFile
from app.core.storage.base import BaseStorage
from app.core.config import settings


class LocalStorage(BaseStorage):
    """本地存储实现"""

    def __init__(self, base_path: str = None, **kwargs):
        super().__init__(**kwargs)
        self.base_path = Path(base_path or settings.UPLOAD_PATH)
        self._ensure_base_path()

    def _ensure_base_path(self):
        """确保基础目录存在"""
        if not self.base_path.exists():
            self.base_path.mkdir(parents=True, exist_ok=True)

    async def save(self, file: Union[BinaryIO, UploadFile], filename: str) -> str:
        """保存文件到本地"""
        try:
            # 生成存储路径
            storage_path = self.generate_storage_path(filename)
            full_path = self.base_path / storage_path

            # 确保目录存在
            full_path.parent.mkdir(parents=True, exist_ok=True)

            # 保存文件
            if isinstance(file, UploadFile):
                with full_path.open("wb") as f:
                    shutil.copyfileobj(file.file, f)
            else:
                with full_path.open("wb") as f:
                    shutil.copyfileobj(file, f)

            return storage_path

        except Exception as e:
            raise Exception(f"文件保存失败: {str(e)}")

    async def delete(self, file_path: str) -> bool:
        """删除本地文件"""
        try:
            full_path = self.base_path / file_path
            if full_path.exists():
                full_path.unlink()
            return True
        except Exception as e:
            return False

    async def get(self, file_path: str) -> Optional[BinaryIO]:
        """获取本地文件"""
        try:
            full_path = self.base_path / file_path
            if not full_path.exists():
                return None
            return full_path.open("rb")
        except Exception:
            return None

    async def get_url(self, file_path: str, expires_in: int = 3600) -> str:
        """获取文件URL"""
        if not self.base_url:
            raise Exception("未配置访问URL")
        return f"{self.base_url}/{file_path}"
